package TangramBase;

import TangramCore.Database;
import TangramCore.Dilek;
import TangramCore.Hladina;
import TangramCore.HladinaEdit;
import TangramCore.HladinaObrazek;
import TangramCore.HladinaObrys;
import TangramCore.Obrazec;
import TangramCore.ObrazecListener;
import TangramCore.Obrys;
import TangramCore.Skladacka;
import TangramCore.Vzhled;
import java.applet.AudioClip;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.MediaTracker;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import org.freehep.util.export.ExportDialog;
//import org.freehep.graphicsio.emf.*;
//import org.freehep.graphicsio.ps.PSGraphics2D;

public class TangramEditFrame extends JFrame implements ObrazecListener, DocumentWindow, WindowStateListener, Database.DatabaseChangeListener {
	static final long serialVersionUID = 24362462L;
	
	private JMenuItem mniThis = null;
    private int iWindow = -1, lastState;
    TangramFrame frmDatabase;
    Database database;
    Skladacka skl;
    Database.ObrazecData odShowed;
    int showed = -1;
    boolean changed = false;
    
    public static final int MODE_SAME = 0, MODE_SOLVE = 1, MODE_NEW = 2, MODE_EDIT = 3; 
    private static final String modeNames[] = {null, "Solve!", "Create...", "Edit"};
    int mode = MODE_SOLVE;
    
    Obrazec obrazec;
    Dilek dSolve[], dNahled[], dVzor[];
    Obrys oSolve, oVzor;
    ArrayList<Hladina> hSolve;
    
    HladinaEdit hEdit;
    HladinaObrys hVzor, hNahled, hHelp;
    HladinaObrazek hObrazek;
    public static String FILE_IMAGE = "pics/logo.png", FILE_SOUND = "sound/solved.wav";
    
    public static int iVzhled = 0;
    static Vzhled vo = Vzhled.getDefaultObrys();
    public static Vzhled vObrys[] = {vo, vo};
    public static Vzhled vDilky[] = {Vzhled.getDefaultDilek(), PentominosConversion.getColoredVzhled()};
    public static Vzhled vDilkySel[] = {Vzhled.getDefaultDilekVyber(), Vzhled.getDefaultDilekVyber()};
    
    public static AudioClip wavSolved = null;
    public TangramEditFrame(TangramFrame frm, Database database) {

        this.frmDatabase = frm;
        FILE_IMAGE = frmDatabase.rootDir + FILE_IMAGE;
        this.database = database;
        //this.mode = mode;
        
        skl = database.getActSet();
        odShowed = database.getDefaultObrazecCopy();
        dSolve = skl.getDilky(odShowed.d);
        dNahled = skl.getDilky(dSolve);
        oSolve = new Obrys(dNahled);
        dVzor = skl.getDilky(dSolve);
        oVzor = new Obrys(dVzor);
        
        hSolve = new ArrayList<Hladina>(4);
        hEdit = new HladinaEdit(dSolve, oSolve, vDilky[iVzhled], vDilkySel[iVzhled], vObrys[iVzhled], null, new Rectangle(0,0,-100,-100));
        hVzor = new HladinaObrys(dVzor, oVzor,Vzhled.getDefaultNahledDilek(),Vzhled.getDefaultNahledFilled(),null, Hladina.CENTER, false,new Rectangle(0,0,-50,-50));
        hNahled = new HladinaObrys(dNahled, oSolve,Vzhled.getDefaultNahledDilek(),Vzhled.getDefaultNahledFilled(),null,Hladina.CENTER, false,new Rectangle(-50,0,-50,-50));
        //hVzor = new HladinaObrys(dVzor, oVzor,Vzhled.getDefaultNahledDilek(),Vzhled.getDefaultNahledFilled(),null, Hladina.CENTER, false,new Rectangle(0,0,565,565));
        //hNahled = new HladinaObrys(dNahled, oSolve,Vzhled.getDefaultNahledDilek(),Vzhled.getDefaultNahledFilled(),null,Hladina.CENTER, false,new Rectangle(800,0,800,800));
        hHelp = new HladinaObrys(dVzor, oVzor,Vzhled.getDefaultNahledDilek(),Vzhled.getDefaultHelp(),null,Hladina.DEFAULT, false,new Rectangle(0,0,-100,-100));
        MediaTracker mt = new MediaTracker(this);
        try {
            File pic = new File(FILE_IMAGE);
            hObrazek = new HladinaObrazek(pic.toURI().toURL(),mt,Hladina.TOP | Hladina.RIGHT, false,new Rectangle(0,0,-100,-100));
            hSolve.add(hObrazek);
        }catch(MalformedURLException ex){}
        
        hSolve.add(hVzor);
        hSolve.add(hNahled);
        hSolve.add(hHelp);
        hSolve.add(hEdit);
        try{
            mt.waitForAll();
        }catch(InterruptedException e){}
        
        setLayout(new BorderLayout(0,0));
        add(obrazec = new Obrazec(skl,Color.white,hSolve,hEdit,dSolve,dNahled,oSolve), BorderLayout.CENTER);
        //obrazec.setBorder(new LineBorder(Color.RED, 10));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(WindowEvent ev){
                ((DocumentWindow)ev.getWindow()).showDocument(false);
            }
        });
        addWindowStateListener(this);
        setSize(800,600);
        TangramFrame.centerOnScreen(this);
        //setExtendedState(Frame.MAXIMIZED_BOTH);
        obrazec.setSize(getWidth(),getHeight());
        obrazec.addObrazecListener(this);
        hObrazek.toggleVisibility();
    }
    
    public void switchMode(int mode){
        this.mode = mode;
        if(mode == MODE_NEW){
            hVzor.hide();
            hHelp.hide();
            hNahled.show();
        }
        else if(mode == MODE_SOLVE || mode == MODE_EDIT){
            hVzor.show();
            hHelp.show();
            hNahled.show();
            //hEdit.hide();
            //hHelp.hide();
        }
        hEdit.prepniVzhled(Hladina.VZHLED_DILKY);
        obrazec.update();
    }
    public void showObrazec(int index, int m){
        setShowed(index, m);//nastavi mod
        switchMode(mode); //zobrazi hladiny pro mod, vcetne update
        setVisible(true);
        toFront();
        obrazec.requestFocus();
    }
    
    public void setDatabase(Database database){//changeSkladacka
        skl = database.getActSet();
        odShowed = database.getDefaultObrazecCopy();
        dSolve = skl.getDilky(odShowed.d);
        dNahled = skl.getDilky(dSolve);
        oSolve = new Obrys(dNahled);
        dVzor = skl.getDilky(dSolve);
        oVzor = new Obrys(dVzor);
        obrazec.setSkladacka(skl,dSolve,dNahled,oSolve);
        hVzor.update(dVzor, oVzor);
        hNahled.update(dNahled, oSolve);
        hHelp.update(dVzor, oVzor);
        obrazec.update();
    }

    private void setTitle(){
        super.setTitle("Board" + sDash + skl.nazev + sLFigureBracket + odShowed.nazev + (changed ? sChanged : sUpToDate) + sRFigureBracket + sDash  + modeNames[mode]);
        setMenuItemText();
    }
    
    public void setShowed(int index, int m){
        showed = index;
        mode = mode == MODE_SAME ? mode : m;
        if(showed < 0 || mode == MODE_NEW){
            Dilek.copyFrom(dVzor, database.getDefaultObrazec().d);
            oVzor.update();
            Dilek.copyFrom(dSolve, dVzor);
            Dilek.copyFrom(dNahled, dVzor);
            oSolve.update();
            odShowed = new Database.ObrazecData(skl,dVzor,oSolve.od);
            changed = true;
            mode = MODE_NEW;
        }
        else {
            if(showed >= database.getSize())
                return;
            odShowed = database.getObrazecData(showed);
            Dilek.copyFrom(dVzor, odShowed.d);
            changed = false;
            oVzor.update();
            if(mode == MODE_EDIT){
                Dilek.copyFrom(dSolve, dVzor);
                Dilek.copyFrom(dNahled, dVzor);
                oSolve.update();
            }
            else if(mode == MODE_SOLVE){
                Dilek.copyFrom(dSolve, database.getDefaultObrazec().d);
                Dilek.copyFrom(dNahled, dSolve);
                oSolve.update();
            }
        }
        obrazec.vyberVse(false);
        setTitle();
    }
    
    public void resetShowed(){
        showed = database.getIndex(odShowed);
    }

    public void mouseDown(MouseEvent e){
        if(e.getButton()==MouseEvent.BUTTON3 && hEdit.getVzhled() == Hladina.VZHLED_OBRYS || oSolve.compare(oVzor))
            obrazec.prepniVzhled();
            if(hEdit.getVzhled() == Hladina.VZHLED_OBRYS && wavSolved != null)
                wavSolved.play();
    }
    
        public void keyDown(KeyEvent e){
        switch (e.getKeyCode()){
            case KeyEvent.VK_PAGE_DOWN:
                showNext();
                break;
            case KeyEvent.VK_PAGE_UP:
                showPrev();
                break;
            case KeyEvent.VK_ENTER:
                Dilek.normalizeAll(dSolve);
                obrazec.update();
                Database.ObrazecData od = e.isShiftDown() ? new Database.ObrazecData(skl, dSolve, oSolve.od) : new Database.ObrazecData(odShowed, dSolve, oSolve);
                int ret = -1;
                if(e.isControlDown())
                    ret = frmDatabase.replaceObrazec(odShowed, od, showed);
                else
                    ret = frmDatabase.addObrazec(od, showed);
                if(ret > -1){
                    Dilek.copyFrom(dVzor,dSolve);
                    oVzor.update(dVzor);
                    showed = ret;
                    showObrazec(showed, MODE_EDIT);
                }
                break;
            case KeyEvent.VK_INSERT:
                hNahled.prepniVzhled();
                hVzor.prepniVzhled();
                obrazec.update();
                break;
            case KeyEvent.VK_H:
                hHelp.toggleVisibility();
                obrazec.update();
                break;
            case KeyEvent.VK_N:
                hNahled.toggleVisibility();
                obrazec.update();
                break;
            case KeyEvent.VK_P:
                hVzor.toggleVisibility();
                obrazec.update();
                break;
            case KeyEvent.VK_O:
                hObrazek.toggleVisibility();
                obrazec.update();
                break;  
            case KeyEvent.VK_B:
                iVzhled = (iVzhled + 1) % vDilky.length;
                hEdit.setVzhled(vDilky[iVzhled], vDilkySel[iVzhled], vObrys[iVzhled]);
                obrazec.update();
                break;
            case KeyEvent.VK_DELETE:
                for(int i=0; i<dSolve.length; i++)
                    dSolve[i].normalize();
                obrazec.update();
                break;
            case KeyEvent.VK_S:
                /*VectorGraphics g = null;
                try{
                g = new PSGraphics2D(new File(odShowed.nazev+".eps"),obrazec.getSize());
                } catch(Exception ex){}
                //Properties p = new Properties();
                //p.setProperty("PageSize","A4");
                //p.setProperty("Orientation","Landscape");
                //g.setProperties(p);
                g.startExport();
                obrazec.print(g);
                g.endExport();*/         
                ExportDialog export = new ExportDialog();
                export.showExportDialog(this, "Export view as ...", obrazec, odShowed.nazev );
                break;
        }
    }
    private void showNext(){
        if(showed < 0){
            setShowed(0, mode);
            switchMode(mode);
            return;
        }
        if(showed < 0 || showed > database.getSize()-2)
            return;
        setShowed(showed+1, mode);
        switchMode(mode);
    }

    private void showPrev(){
        if(showed < 1)
            return;
        setShowed(showed-1, mode);
        switchMode(mode);
    }

    public void changed(){
        if(mode == MODE_EDIT && !changed){
            changed = true;
            setTitle();
        }
    }
    
    public void restoreState(){
        setExtendedState(lastState);
        toFront();
    }
    
    private void setMenuItemText(){
        if(mniThis != null)
            mniThis.setText(sLNumberBracket + iWindow + /*(changed ? sChanged : sUpToDate) + */sRNumberBracket + getTitle());
    }
    
    public void setMenuItem(int i, JMenuItem mni){
        iWindow = i;
        mniThis = mni;
        setMenuItemText();
    }
    
    public void windowStateChanged(WindowEvent ev){
        if((ev.getNewState() & JFrame.ICONIFIED) != 0)
            lastState = ev.getOldState();
    }
    public boolean showDocument(boolean jak){
        boolean ret = jak ? frmDatabase.windowOpened(this):frmDatabase.windowClosed(this);
        setVisible(jak);
        if(jak)
            toFront();
        else
            dispose();
        return ret;
    }

    public boolean databaseChanged(int what, int i){
        if(showed < 0)
            return true;
        if(i < 0)
            showed = database.getIndex(odShowed);
        else if(showed == i && (what & Database.CHANGED_OBRAZEC) != 0)
            showed = -1;
        if(showed < 0){
            //odShowed = new Database.ObrazecData(odShowed, dVzor, oVzor);
            showed = -1;
            changed = true;
        }
        setTitle();
        return true;
    }
    public boolean hasChanged(){
        return changed;
    }

}
    
